﻿using Newtonsoft.Json;
using RM.BasicLibrary.Enums;
using RM.BasicLibrary.Requests;
using RM.BasicLibrary.Resources;
using System;
using System.Diagnostics;

namespace RM.BasicLibrary.Exceptions
{
    /// <summary>
    /// 异常过滤器
    /// </summary>
    public interface IFilter
    {
        /// <summary>
        /// 带异常抛出的异常过滤器
        /// </summary>
        /// <param name="action"></param>
        /// <param name="baseBusinessException"></param>
        void Execute(Action action, BaseException baseBusinessException);
        /// <summary>
        /// 带消息的异常过滤器
        /// </summary>
        /// <param name="func"></param>
        /// <param name="msg"></param>
        void Execute(Action func, string msg = "");
        void Execute(Action action, Action exHander, string ex = null);
        void Execute(Action action, Action exHander, string ex = null, BaseException baseBusinessException = null);
    }
    /// <summary>
    /// 异常处理器
    /// </summary>
    public interface IHandler
    {
        string SucceedMsg { get; set; }
        /// <summary>
        /// 带参数的异常处理器返回给api  实现BaseBusinessException，手动抛出的异常都会释放给前端msg
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <returns></returns>
        Respose<T> Execute<T>(Action<Respose<T>> func);
        /// <summary>
        /// 不带参数的异常处理器返回给api 实现BaseBusinessException，手动抛出的异常都会释放给前端msg
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <returns></returns>
        Respose Execute(Action func);
        Respose Execute(Action func, Action<Respose> exHander = null, string errorMsg = null, string succeedMsg = null);
    }
    public abstract class ExceptionAbstract
    {
        public string SucceedMsg { get; set; } = "执行成功！";
        /// <summary>
        /// 获取错误码
        /// </summary>
        /// <param name="action"></param>
        /// <param name="status"></param>
        /// <param name="msg"></param>
        private void GetStatus(Action action, out Status status, out string msg)
        {
            status = Status.Succeed;
            msg = Status.Succeed.ToString();
            try
            {
                action?.Invoke();
            }
            catch (BusinessException businessEx)
            {
                status = Status.BLLError;
                msg = businessEx.BaseExceptionInfo.Msg;
            }
            catch (ParameterException ex)
            {
                status = Status.ParameterError;
                msg = ex.BaseExceptionInfo.Msg;
            }
            catch (BasicLibraryException ex)
            {
                status = Status.EnterpriseError;
                msg = ex.BaseExceptionInfo.Msg;
                Root.BasicIns.Log.Error(ex.BaseExceptionInfo.Msg, ex);
            }
            catch (BasicException ex)
            {
                status = Status.EnterpriseError;
                var codeInfo = JsonConvert.DeserializeObject<CodeInfo>(ex.Message);
                msg = codeInfo.Msg;
                Root.BasicIns.Log.Error(ex.BaseExceptionInfo.Msg, ex);
            }
            catch (BaseException baseEx)
            {
                status = Status.BLLError;
                msg = baseEx.BaseExceptionInfo.Msg;
            }

            catch (SystemException ex)
            {
                status = Status.SystemError;
                msg = ex.Message;
                Root.BasicIns.Log.Error(ex.Message, ex);
            }
            catch (Exception ex)
            {
                status = Status.SystemError;
                msg = Root.BasicIns.GetValue(ExceptionsResource.SystemError);
                Root.BasicIns.Log.Error(ex.Message, ex);
            }
        }
        protected virtual Respose<T> Handler<T>(Action<Respose<T>> func)
        {
            Respose<T> request = new Respose<T>();
            GetStatus(() => func?.Invoke(request), out Status status, out string msg);
            request.Status = status;
            request.Msg = msg;
            return request;
        }
        protected Respose Handler(Action func)
        {
            Respose request = new Respose();
            GetStatus(() => func?.Invoke(), out Status status, out string msg);
            request.Status = status;
            request.Msg = msg;
            return request;
        }
        protected Respose Handler(Action func, Action<Respose> exHander=null, string errorMsg = null, string succeedMsg = null)
        {
            Respose request = new Respose();
            GetStatus(() => func?.Invoke(), out Status status, out string msg);
            request.Status = status;
            request.Msg = request.Status == Status.Succeed ? succeedMsg ?? SucceedMsg : errorMsg ?? msg;
            exHander?.Invoke(request);
            return request;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="action"></param>
        /// <param name="baseBusinessException"></param>
        protected void Filter(Action action, BaseException baseBusinessException)
        {
            Filter(action, exHander: null, ex: "", baseBusinessException: baseBusinessException);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="action"></param>
        /// <param name="exHander"></param>
        /// <param name="ex"></param>
        /// <param name="baseBusinessException"></param>
        protected void Filter(Action action, Action exHander, string ex = null, BaseException baseBusinessException = null)
        {
            try
            {
                action?.Invoke();
            }
            catch (Exception exception)
            {
                ShowMsg(exception.Message);
                exHander?.Invoke();
                if (!ex.IsNull())
                {
                    if (!ex.IsNull()) ex = new CodeInfo().GetCodeInfo(4, true, ex, exception).ToJson();
                    throw new BasicException(ex, exception);
                }
                if (baseBusinessException != null) throw baseBusinessException;
                Root.BasicIns.Log.Error(exception.Message, exception);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="action"></param>
        /// <param name="ex"></param>
        protected void Filter(Action action, string ex = null)
        {
            Filter(action, exHander: null, ex: ex, baseBusinessException: null);
        }
        protected void ShowMsg(int isShow, string msg)
        {
            Debug.WriteIf(isShow > (int)Status.EnterpriseError, msg);
        }
        protected void ShowMsg(string msg)
        {
            Debug.WriteIf(true, msg);
        }
    }
    /// <summary>
    /// 异常处理
    /// </summary>
    public class ExceptionFilter : ExceptionAbstract, IFilter
    {
        /// <summary>
        /// 带消息的异常过滤器
        /// </summary>
        /// <param name="func"></param>
        /// <param name="msg"></param>
        public void Execute(Action func, string msg = "")
        {
            Execute(func, null, msg, null);
        }
        /// <summary>
        /// 带异常抛出的异常过滤器
        /// </summary>
        /// <param name="action"></param>
        /// <param name="baseBusinessException"></param>
        public void Execute(Action action, BaseException baseBusinessException)
        {
            Execute(action, null, null, baseBusinessException);
        }

        public void Execute(Action action, Action exHander, string ex = null)
        {
            Execute(action, exHander, ex, null);
        }

        public void Execute(Action action, Action exHander, string ex = null, BaseException baseBusinessException = null)
        {
            Filter(action, exHander, ex, baseBusinessException);
        }
    }
    public class ExceptionHandler : ExceptionAbstract, IHandler
    {
        public Respose Execute(Action func)
        {
            var result = Handler(func);
            ShowMsg((int)result.Status, result.Msg);
            return result;
        }
        public Respose<T> Execute<T>(Action<Respose<T>> func)
        {
            var result = Handler(func);
            ShowMsg((int)result.Status, result.Msg);
            return result;
        }
        public Respose Execute(Action func, Action<Respose> exHander = null, string errorMsg = null, string succeedMsg = null)
        {

            var result = Handler(func, exHander, errorMsg, succeedMsg);
            ShowMsg((int)result.Status, result.Msg);
            return result;
        }
    }
}
